一堆樸克牌攤在眼前,要照花色排還是大小來排?隨你高興。
sort()
是個很好用的陣列方法,凡是要把陣列裡面的元素,照我們想排列的方式重新排列都需要用到它。例如在購物網站的商品依價格排列,或是我們看文章時,依照最近的時間排列,都會用到sort()
。
在做排序時,我們也會同時原地(in place)的更動到原陣列,且回傳給我們排好序的陣列。
Array.prototype.sort() - JavaScript | MDN
原型: Array.prototype.sort()
功能: 依據字串的 Unicode 編碼進行排序。
改變: 會改變原本的陣列
語法: arr.sort([compareFunction])
回傳值: 回傳排序後的陣列
參數: 可指定一個函式來定義排序的順序。如果省略此參數就會依據字串的 Unicode 編碼進行排序。
sort()
是如何依照我們想要的方式排序?如果我們不給sort()
參數,它會依照預設的方式排序。我們也可以給一個函式當參數,並將條件寫在函式裡,這樣會比沒有給參數精準很多。
預設排序也就是依照我們陣列裡元素的 code UTF-16 的順序排列,什麼是 code UTF-16? UTF-16 是 Unicode 字元的一種,我們可以直接看看這張 Unicode 的編碼表,並且來做一些測試:
const arr1 = [null, 2, 8, undefined, NaN, 200, "Hi", "apple", "", "#", "!", "2"];
arr1.sort();
arr1;
//[ '', '!', '#', '2', 2, 200, 8, 'Hi', NaN, 'apple', null, undefined ]
排序的結果頗讓人驚訝 簡直像沒排序,sort()
會將所有元素轉成字串後,且以第一個字元為對象,再進行排序,而所有符號會被先篩選出來,接著是數字,然後是字母。也因為這樣的比較,所以連200
都會排在8
前面。而字母則以字母大寫為先、小寫為後來排序。
需要特別注意的是,這樣的結果有可能因sort()
執行環境 也就是瀏覽器的不同,而有預期之外的預設排序結果。所以一般會建議,還是以函式傳入參數來當排序條件會比較穩定。
如果希望完全依照自己給的條件排序,最好是給sort()
一個帶有條件的匿名函式來當參數,這個匿名函數必須要有兩個參數,然後再依照這兩個參數比較回傳的值,來當排序依據。
sort()
會依匿名函式的參數與回傳的值為精確的排序規則:
這個函式會每次都先拿兩組陣列裡的元素來比較,當回傳值為正,會讓後面的數跑到前面,以上述的規則來移動元素,大家有沒覺得這種方式很眼熟,其實就是使用冒泡排序法來達到排序。
我們先來看這些例子:
// 沒有給參數的預設排序
const arr = [5, 9, 1, 3, 2, 6];
arr.sort(); // [1, 2, 3, 5, 6, 9]
// 以匿名函式回參數做「升序」排序
arr.sort(function(a, b) {
return a - b; // a - b > 0
});
// [1, 2, 3, 5, 6, 9]
// 如果要反過來做「降序」排序
arr.sort(function(a, b) {
return b - a;
});
// [9, 6, 5, 3, 2, 1]
或許大家會覺得疑惑,怎麼回傳一個 a - b
就變升序 b - a
就成了降序?
這是被精簡化的寫法 聽說高手都會越寫越精簡 ,我們可以來看看原本的寫法:
const arr = [5, 9, 1, 3, 2, 6];
// 升序
arr.sort(function(a, b) {
if(a > b){
return 1; // 正數時,後面的數放在前面
} else {
return -1 // 負數時,前面的數放在前面
}
});
// 降序
arr.sort(function(a, b) {
if(a < b){
return 1; // 正數時,後面的數放在前面
} else {
return -1 // 負數時,前面的數放在前面
}
});
// 升序 另一種寫法,就會精簡到像最上面那樣!
arr.sort(function(a, b) {
if(a > b){ // a > b 等於 a - b > 0
return a - b;
} else {
return a - b
}
});
這就是程式好玩的地方,一步步的精簡到回傳a - b
就是升、b - a
就是降,還真是新手想不出來的境界啊!
sort()
可以運用的範圍很廣,尤其是參數的匿名函式,依照下的條件不同而達到我們想要的效果。來看看一些範例:
const arr = ["hi", "Hello", "Bonjour", "ciao"];
arr.sort(function(a, b){
return a.length - b.length;
});
// ["hi", "ciao", "Hello", "Bonjour"]
我們在最開頭的時候有聊到,sort()
的預設會以 Unicode 來排序,而在 Unicode 的排序裡,大寫字母又會比小寫前面,但當我們要對有大小寫混雜的字串陣列做排序時,如何做到不區分大小寫的排序?可參考下列的方式,先把字串全轉成小寫再比對,就可以得到不分大小寫的排序囉。
arr =["apple", "Banana", "coco", "Ege"];
// 直接預設排序的結果
arr.sort(); // ["Banana", "Ege", "apple", "coco"]
// 先將字串全轉成小寫再排序
arr.sort(function(x, y){
let a = x.toLowerCase();
let b = y.toLowerCase();
if(a > b) return 1;
if(a < b) return -1;
else return 0;
});
// ["apple", "Banana", "coco", "Ege"]
今天就先介紹到這裡,其實sort()
的學問很大,這其中牽涉到的不只是演算法,還有 JavaScript 裡的匿名函式的活用,本人才疏且學淺,好多知識都還來不及吸收,以致不敢介紹給大家,期待有朝一日的自己,可以回頭講解得更清楚些。
如有需要改進的地方,拜託懇求請告知,我會盡量快速度修改,感謝您~